using HelpDeskTool.Entities;
using HelpDeskTool.Utils;
using HelpDeskTool.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Management.Infrastructure;
using Microsoft.Management.Infrastructure.Options;

namespace HelpDeskTool.Services;

public class Wmi : Cimv2, IWmi
{
	private readonly ILogger logger;

	public Wmi(ILogger<Wmi> logger)
	{
		this.logger = logger;
	}

	public async Task<WmiInfo> GetInfoAsync(string hostname, CancellationToken cancellationToken = default)
	{
		var hardware = new Hardware();
		var lastBootUp = (DateTime?)default;
		var operatingSystem = (string?)default;

		var cimSessionOptions = new CimSessionOptions
		{
			Timeout = TimeSpan.FromMilliseconds(100)
		};

		using var cimSession = CimSession.Create(hostname, cimSessionOptions);

		if (!cimSession.TestConnection())
			throw new Exception($"'{hostname}' is not available!");

		var parallelOptions = new ParallelOptions
		{
			MaxDegreeOfParallelism = Environment.ProcessorCount,
			CancellationToken = cancellationToken
		};

		await Tasks.TryParallelRunAsync(logger.LogException, parallelOptions,
			() => hardware.Motherboard = GetMotherBoard(cimSession),
			() => hardware.CPUs = GetCPU(cimSession),
			() => hardware.RAM = GetInfoRamModules(cimSession).ToArray(),
			() => hardware.GPUs = GetGPU(cimSession),
			() => hardware.NetworkAdapters = GetNetworkAdapters(cimSession),
			() => hardware.StorageDisks = GetInfoStorageDisks(cimSession).ToArray(),
			() => hardware.Monitors = GetInfoMonitors(cimSession).ToArray(),
			() => lastBootUp = GetLastBootUp(cimSession),
			() => operatingSystem = GetOperatingSystem(cimSession));

		return new WmiInfo
		{
			Hardware = hardware,
			LastBootUp = lastBootUp,
			OperatingSystem = operatingSystem,
			Updated = DateTime.Now
		};
	}
}
